use crate::{JwtClaims, WebResponseSupportTrait};
use chrono::Local;
use salvo::prelude::JwtAuthDepotExt;
use salvo::{handler, Depot, Request, Response};
use serde::Serialize;
use serde_json::Value;
use std::collections::HashMap;
use std::str::FromStr;
use std::sync::Arc;
use visit_dd_core::i18n_text::{E_ARG_BAD, E_ARG_MISS, E_NO_PERMISSION_FOR_ACTION};
use visit_dd_core::model::VddModel;
use visit_dd_core::proj::APP_CONFIG;
use visit_dd_core::query::VddValueEvaluation;
use visit_dd_core::query::WebQueryParams;
use visit_dd_core::visit::{
    ShareRuleOfField, ShareRuleOfModel, VisitGroup, VisitGroupType, VisitRequest,
};
use visit_dd_core::{i18n, Astr, JsonSupportTrait, ProjectRsaHelper, UserId};
use visit_dd_db::query_db::page;
use visit_dd_db::{model_db, subscribe, user_db, visit_db};

/// 检查共享访问权限的返回结果
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct CheckAuthResponse {
    pub vg: Option<Arc<VisitGroup>>,
    pub vr: Option<Arc<VisitRequest>>,
    pub subscribed: bool,
    pub pass: bool,
}
///
#[derive(Serialize)]
struct MyTokens {
    pub vgs: Vec<Arc<VisitGroup>>,
    pub models: Vec<Arc<VddModel>>,
}
///
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct ListShareModelResponse {
    pub model: Arc<VddModel>,
    pub visitor_count: u32,
    pub req_sum: u16,
    pub visit_status: Astr,
}

///
#[handler]
pub(crate) async fn g_tag_status(_req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let jwt = &depot.jwt_auth_data::<JwtClaims>().unwrap().claims;
    let model_ids = model_db::m_select_ids_by_uid(&jwt.uid).await;
    let mut status_map = HashMap::<u64, Arc<str>>::new();
    let model_tags = model_db::m_select_tags_to_map(true, false, None).await;
    for model_id in model_ids {
        match model_tags.get(&model_id) {
            None => {
                status_map.insert(model_id, i18n!(1024));
            }
            Some(model_tag) => {
                if model_tag.is_empty() {
                    status_map.insert(model_id, i18n!(1024));
                }
                if model_db::m_is_all_field_have_tag(model_id, &model_tag).await {
                    status_map.insert(model_id, i18n!(1025));
                } else {
                    status_map.insert(model_id, i18n!(1026));
                }
            }
        }
    }
    res.ok(&status_map);
}

/// 作废访问凭证
#[handler]
pub(crate) async fn p_drop_token(req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let jwt = &depot.jwt_auth_data::<JwtClaims>().unwrap().claims;
    let model_id = req
        .params()
        .get("model-id")
        .cloned()
        .expect(i18n!(E_ARG_MISS).as_ref());
    let model_id = u64::from_str(&model_id).expect(i18n!(E_ARG_BAD).as_ref());
    let vg = visit_db::vg_try_load_in_model_by_user(model_id, &jwt.uid)
        .await
        .unwrap();
    // info!("{:?}",vg);
    // 判断是否有权限操作，是否是作者，访问组里是否有他
    let model = model_db::m_load(model_id).await;
    if model.uid != jwt.uid && vg.u_id != jwt.uid {
        res.error(i18n!(1101).as_ref());
        return;
    }
    let r = visit_db::vg_close(&vg, &jwt.uid).await;
    if r.is_err() {
        res.error(&r.unwrap_err());
    } else {
        res.ok_empty();
    }
}

/// 获取用户已经获得的访问授权
#[handler]
pub(crate) async fn g_my_token(_req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let jwt = &depot.jwt_auth_data::<JwtClaims>().unwrap().claims;
    let vgs = visit_db::vg_select_by_user_id(&jwt.uid).await;
    let mut models = Vec::<Arc<VddModel>>::new();
    for vg in vgs.iter() {
        let model = model_db::m_load(vg.model_id).await;
        models.push(model);
    }
    res.ok(&MyTokens { vgs, models });
}

/// 保存一个模型的分享组
#[handler]
pub(crate) async fn p_save_vg(req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let jwt = &depot.jwt_auth_data::<JwtClaims>().unwrap().claims;
    let j = req.parse_body::<Value>().await.unwrap();
    let model_id = j["modelId"].as_u64().expect(&i18n!(E_ARG_BAD));
    let model = model_db::m_load(model_id).await;
    if jwt.uid != model.uid {
        res.error(&i18n!(E_NO_PERMISSION_FOR_ACTION));
        return;
    }
    let vg = VisitGroup::try_from(&j);
    let Ok(mut vg) = vg else {
        res.error(&i18n!(E_ARG_BAD));
        return;
    };
    match j["uIds"].as_array() {
        Some(values) => {
            for v in values.iter() {
                if let Some(uid) = v.as_u64() {
                    if uid > 0 {
                        vg.u_id = UserId(uid);
                        visit_db::vg_save(&vg, &jwt.uid).await.unwrap();
                    }
                }
            }
            res.ok_empty();
        }
        None => {
            res.error(&i18n!(E_ARG_BAD));
        }
    }
}

#[handler]
pub(crate) async fn p_remove_vg(req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let jwt: &JwtClaims = &depot.jwt_auth_data::<JwtClaims>().unwrap().claims;
    let j: Value = req.parse_body::<Value>().await.expect(i18n!(9002).as_ref());
    let model_id = j["modelId"].as_u64().expect(i18n!(E_ARG_BAD).as_ref());
    let u_id = j["uId"].as_u64().expect(i18n!(E_ARG_BAD).as_ref());
    let vg = visit_db::vg_load(model_id, UserId(u_id)).await;
    let model = model_db::m_load(model_id).await;
    if model.uid != jwt.uid {
        res.error(i18n!(E_NO_PERMISSION_FOR_ACTION).as_ref());
        return;
    }
    // 删除组信息
    let r = visit_db::vg_close(&vg, &jwt.uid).await;
    res.wrap(r);
}

/// 设定或者修改一个模型的标记
#[handler]
pub(crate) async fn p_save_tags(req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let jwt = &depot.jwt_auth_data::<JwtClaims>().unwrap().claims;
    let j: Value = req.parse_body::<Value>().await.unwrap();
    let model_id = j["modelId"].as_u64().unwrap();
    let schema = visit_dd_db::cache::get_schema(model_id).await.unwrap();
    if schema.model.store.is_some() {
        res.error("远端存放数据的模型不支持自定义标记");
        return;
    }
    let model_tag = j["modelCode"].as_str().unwrap();
    if !model_db::m_is_tag_unique(model_tag, model_id).await {
        res.error(i18n!(1028).as_ref());
    } else {
        let mut tag_map: HashMap<Astr, u64> = HashMap::new(); //存放字段的标记
        let mut msg: Astr = Arc::from("");
        if j["fields"].is_array() {
            j["fields"].as_array().unwrap().iter().for_each(|item| {
                let tag = item["code"].as_str().expect(i18n!(E_ARG_BAD).as_ref());
                if tag.starts_with("_") {
                    msg = i18n!(1029);
                    return;
                }
                if tag_map.get(tag).is_some() {
                    //判断是否有重复的字段标记
                    if msg.is_empty() {
                        msg = i18n!(1030, tag);
                    } else {
                        msg = i18n!(1031, &msg, tag);
                    }
                    return;
                } else {
                    tag_map.insert(tag.into(), item["id"].as_u64().unwrap());
                }
            });
        }
        if msg.is_empty() {
            let model = model_db::m_load(model_id).await;
            if jwt.uid != model.uid {
                res.error(i18n!(E_NO_PERMISSION_FOR_ACTION).as_ref());
            } else {
                let r = model_db::m_save_tags(&model, model_tag, &tag_map).await;
                res.wrap(r);
            }
        } else {
            res.error(&msg);
        }
    }
}

/// 获取当前系统所有分享出来的模型
#[handler]
pub(crate) async fn g_shared_models(_req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let jwt: &JwtClaims = &depot.jwt_auth_data::<JwtClaims>().unwrap().claims;
    let models = model_db::m_select_sharing(&jwt.uid).await;
    // 平台内所有的访问组列表，用以比对
    let all_vg = visit_db::vg_select_all().await;
    // 模型内有访问权限的用户数
    let mut uid_count_map = HashMap::<u64, u32>::new();
    // 当前用户对所有模型最大权限的访问组
    let mut user_vg_map = HashMap::<u64, Arc<VisitGroup>>::new();
    all_vg.iter().for_each(|vg| {
        let mut count = *uid_count_map.get(&vg.model_id).unwrap_or(&0);
        count = count + 1;
        uid_count_map.insert(vg.model_id, count);
        // info!("{:?}", vg.group_type);
        // 自己的访问组
        if vg.u_id == jwt.uid {
            user_vg_map.insert(vg.model_id, vg.clone());
        }
        // 匿名访问组
        if vg.accept_anonymouse() && user_vg_map.get(&vg.model_id).is_none() {
            user_vg_map.insert(vg.model_id, vg.clone());
        }
    });
    // info!("{:?}", ids);
    // info!("{:?}", uid_count_map);
    // info!("{:?}", author_map);
    let mut res_data = Vec::<ListShareModelResponse>::new();
    for model in models.iter() {
        let c = visit_db::vr_count_in_model(model.id).await.unwrap(); // 访问请求数
        let user_vg = user_vg_map.get(&model.id);
        let auth_status = if let Some(user_vg) = user_vg {
            user_vg.get_auth_status(&jwt.uid).to_string()
        } else {
            let vr = visit_db::vr_try_load_in_model_by_user(model.id, &jwt.uid).await;
            match vr {
                None => "无访问权限".to_string(),
                Some(vr) => match vr.accept_ts {
                    None => "已申请等待通过中".to_string(),
                    Some(..) => "申请被拒绝".to_string(),
                },
            }
        };
        let item = ListShareModelResponse {
            model: model.clone(),
            visitor_count: *uid_count_map.get(&model.id).unwrap_or(&0),
            req_sum: c.0 as u16,
            visit_status: Arc::from(auth_status),
        };
        res_data.push(item);
    }
    res.ok(&res_data);
}

/// 检查一个用户对于一个模型是否有访问授权
#[handler]
pub(crate) async fn p_check_auth(req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let jwt = &depot.jwt_auth_data::<JwtClaims>().unwrap().claims;
    let model_id = req.params().get("model-id").cloned().unwrap();
    let model_id = u64::from_str(&model_id).unwrap();
    let vr = visit_db::vr_try_load_in_model_by_user(model_id, &jwt.uid).await;
    let vg = visit_db::vg_try_load_in_model_by_user(model_id, &jwt.uid).await;
    let subscribed = subscribe::sc_load(model_id, &jwt.uid).await.is_ok();
    res.ok(&CheckAuthResponse {
        pass: vg.is_some(),
        vg,
        vr,
        subscribed,
    });
}

/// 列出一个模型的访问请求
#[handler]
pub(crate) async fn g_requests(req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let jwt = &depot.jwt_auth_data::<JwtClaims>().unwrap().claims;
    let model_id = req
        .params()
        .get("model-id")
        .cloned()
        .expect(i18n!(E_ARG_MISS).as_ref());
    let model_id = u64::from_str(&model_id).expect(i18n!(E_ARG_BAD).as_ref());
    let model = model_db::m_load(model_id).await;
    if model.uid != jwt.uid {
        res.error("不是自己的模型，没有权限进行此操作");
    } else {
        let share_requests = visit_db::vr_select_in_model(model_id).await;
        res.ok(&share_requests);
    }
}

/// 通过或者拒绝一个访问请求
#[handler]
pub(crate) async fn p_handle_request(req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let jwt: &JwtClaims = &depot.jwt_auth_data::<JwtClaims>().unwrap().claims;
    let j: Value = req.parse_body::<Value>().await.unwrap();
    if j.get("modelId").is_none() || j.get("requestUid").is_none() {
        res.error(i18n!(E_ARG_BAD).as_ref());
        return;
    }
    let model_id = j["modelId"].as_u64().unwrap();
    let model = model_db::m_load(model_id).await;
    if model.uid != jwt.uid {
        res.error(i18n!(E_NO_PERMISSION_FOR_ACTION).as_ref());
        return;
    }
    let req_uid = j["requestUid"].as_u64().expect(i18n!(E_ARG_BAD).as_ref());
    let vr = visit_db::vr_try_load_in_model_by_user(model_id, &UserId(req_uid)).await;
    if vr.is_none() {
        res.error(i18n!(1103).as_ref());
        return;
    }
    let mut vr = vr.unwrap();
    if j.has_useful_str("denyHint") {
        // 拒绝请求
        let vr = Arc::get_mut(&mut vr).unwrap();
        vr.accept_ts = Some(Local::now().naive_local());
        vr.deny_hint = Some(Arc::from(j["denyHint"].as_str().unwrap_or("拒绝")));
        let _ = visit_db::vr_save(&vr, &jwt.uid, true).await;
        res.ok(&vr);
        return;
    }
    let mut limits = Vec::<Arc<ShareRuleOfField>>::new();
    j["limits"].as_array().map(|x| {
        x.iter().for_each(|y| {
            let limit = ShareRuleOfField::try_from(y);
            if limit.is_ok() {
                limits.push(limit.unwrap().into());
            }
        })
    });
    let mut filters = Vec::<Arc<VddValueEvaluation>>::new();
    j["filters"].as_array().map(|x| {
        x.iter().for_each(|y| {
            let filter = VddValueEvaluation::try_from(y);
            if filter.is_ok() {
                filters.push(filter.unwrap().into());
            }
        })
    });
    let mut rights = Vec::<Arc<ShareRuleOfModel>>::new();
    j["rights"].as_array().map(|x| {
        x.iter().for_each(|y| {
            let rigth = ShareRuleOfModel::try_from(y);
            if rigth.is_ok() {
                rights.push(rigth.unwrap().into());
            }
        })
    });
    // 给申请的用户选一个或者新建一个访问组
    let r = visit_db::vg_from_vr(&vr, &limits, &filters, &rights).await;
    if let Err(e) = r {
        res.error(&e);
        return;
    }
    let vr = Arc::get_mut(&mut vr).unwrap();
    vr.accept_ts = Some(Local::now().naive_local());
    visit_db::vr_save(&vr, &jwt.uid, true).await.unwrap();
    let vg = visit_db::vg_load(model_id, vr.request_uid.clone()).await;
    res.ok(&vg);
}

/// 发送对一个模型的访问请求
#[handler]
pub(crate) async fn p_send_request(req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let jwt: &JwtClaims = &depot.jwt_auth_data::<JwtClaims>().unwrap().claims;
    let j: Value = req.parse_body::<Value>().await.unwrap();
    let model_id = j["modelId"].as_u64().expect(i18n!(E_ARG_BAD).as_ref());
    let vgt = VisitGroupType::try_from(&j).unwrap();
    let rights = j["rights"]
        .as_array()
        .map(|x| {
            x.iter()
                .map(|y| ShareRuleOfModel::try_from(y))
                .filter(|y| y.is_ok())
                .map(|y| Arc::new(y.unwrap()))
                .collect::<Vec<Arc<ShareRuleOfModel>>>()
        })
        .unwrap_or(Vec::new());
    let write_able = j["writeAble"].as_bool().unwrap_or(false);
    if write_able && vgt.is_anon_type() {
        res.error("匿名访问不支持任何数据变更操作");
        return;
    }
    let vr = VisitRequest {
        model_id,
        request_uid: jwt.uid.to_owned(),
        vgt: vgt.into(),
        rights,
        write_able,
        request_ts: Local::now().naive_local(),
        accept_ts: None,
        deny_hint: None,
    };
    let r = visit_db::vr_save(&vr, &jwt.uid, false).await;
    res.wrap(r);
}

/// 校验访问密码或授权码
#[handler]
pub(crate) async fn p_verify_code(req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let jwt = &depot.jwt_auth_data::<JwtClaims>().unwrap().claims;
    let j: Value = req.parse_body::<Value>().await.unwrap();
    if j.get("modelId").is_none() || j.get("aCode").is_none() {
        res.error(i18n!(E_ARG_BAD).as_ref());
        return;
    }
    let model_id = j["modelId"].as_u64().unwrap();
    let vg = visit_db::vg_try_load_in_model_by_user(model_id, &jwt.uid).await;
    if vg.is_none() {
        res.error(i18n!(1101).as_ref());
    } else {
        let vg = vg.unwrap();
        let rsa_helper = ProjectRsaHelper::init(&APP_CONFIG.pri_key, &APP_CONFIG.pub_key);
        let a_code = rsa_helper.decode_b64str(j["k"].as_str().unwrap()).unwrap();
        match vg.group_type.as_ref() {
            VisitGroupType::VgtPubKey => {
                let user = user_db::u_load(&vg.u_id, false, true).await;
                if a_code != user.pub_key.as_ref() {
                    res.error(i18n!(1104).as_ref());
                } else {
                    res.ok_empty();
                }
            }
            _ => {
                res.error(i18n!(1101).as_ref());
            }
        }
    }
}

#[handler]
pub(crate) async fn g_visit_groups(req: &mut Request, depot: &mut Depot, res: &mut Response) {
    let jwt: &JwtClaims = &depot.jwt_auth_data::<JwtClaims>().unwrap().claims;
    let model_id = req
        .params()
        .get("model-id")
        .cloned()
        .expect(i18n!(E_ARG_MISS).as_ref());
    let model_id = u64::from_str(&model_id).expect(i18n!(E_ARG_BAD).as_ref());
    let model = model_db::m_load(model_id).await;
    if model.uid != jwt.uid {
        res.error(i18n!(E_NO_PERMISSION_FOR_ACTION).as_ref());
    } else {
        let vgs = visit_db::vg_select_in_model(model_id).await;
        res.ok(&vgs);
    }
}

/// 获取一个模型的示例记录10条
#[handler]
pub(crate) async fn g_record_sample(req: &mut Request, _depot: &mut Depot, res: &mut Response) {
    let model_id = req
        .params()
        .get("model-id")
        .cloned()
        .expect(i18n!(E_ARG_MISS).as_ref());
    let model_id = u64::from_str(model_id.as_str()).expect(i18n!(E_ARG_BAD).as_ref());
    let p = WebQueryParams {
        model_id: Some(model_id),
        page_index: 1,
        page_size: 10,
        last_id: 0,
        filters: vec![],
        new_to_old: false,
    };
    res.ok(&page(&p).await);
}
